import { deepCopy, HttpResponse } from '@/core';
import { IContext, IHttpResponse, IParam } from '@/core/interface';
import { ControlVOBase } from '../control-vo';
import { CtrlServiceBase } from './ctrl-service-base';

/**
 * 表格部件服务
 *
 * @class GridService
 */
class GridService<T extends ControlVOBase> extends CtrlServiceBase<T> {
	/**
	 * 备份原生数据
	 *
	 * @type {*}
	 * @memberof GridService
	 */
	private copynativeData: any;

	/**
	 * 远端数据
	 *
	 * @type {*}
	 * @memberof GridService
	 */
	private remoteCopyData: any = {};

	/**
	 * 处理
	 *
	 * @param {string} action
	 * @param {IHttpResponse} response
	 * @return {*}
	 * @memberof GridService
	 */
	handleResponse(response: IHttpResponse, opts: IParam = {}) {
		if (!response.data) {
			return response;
		}
		let result = null;
		const handleResult = () => {
			if (response.data instanceof Array) {
				result = [];
				response.data.forEach((item: IParam) => {
					result.push(this.newControlVO(item));
				});
			} else {
				result = this.newControlVO(response.data);
			}
			// response状态，头文件
			if (response.config) {
				if (response.config['x-page']) {
					Object.assign(response, { page: Number(response.config['x-page']) });
				}
				if (response.config['x-per-page']) {
					Object.assign(response, {
						size: Number(response.config['x-per-page']),
					});
				}
				if (response.config['x-total']) {
					Object.assign(response, {
						total: Number(response.config['x-total']),
					});
				}
			}
			response.data = result;
		};
		handleResult();
		return response;
	}

	/**
	 * 搜索数据
	 *
	 * @param {string} action
	 * @param {IParam} [context={}]
	 * @param {IParam} [data={}]
	 * @return {*}  {Promise<IHttpResponse>}
	 * @memberof GridService
	 */
	async search(
		action: string,
		context: IContext = {},
		data: IParam = {}
	): Promise<IHttpResponse> {
		const { data: Data, context: Context } = this.handleRequestData(
			context,
			data
		);
		try {
			await this.initEntityService();
			if (this.appEntityService) {
				const response: IHttpResponse = await this.appEntityService[
					action ? action : 'FetchDefault'
				](Context, Data);
				this.setCopynativeData(response.data);
				this.handleResponse(response);
				return response;
			}
			return new HttpResponse({ message: '无实体服务' }, null, 500);
		} catch (error) {
			return new HttpResponse(error, null, 500);
		}
	}

	async loadDraft(
		action: string,
		context: IContext = {},
		data: IParam = {}
	): Promise<IHttpResponse> {
		const { data: Data, context: Context } = this.handleRequestData(
			context,
			data
		);
		try {
			await this.initEntityService();
			if (this.appEntityService) {
				const response: IHttpResponse = this.appEntityService[
					action ? action : 'GetDraft'
				](Context, Data);
				this.setRemoteCopyData(response);
				this.handleResponse(response);
				return response;
			}
			return new HttpResponse({ message: '无实体服务' }, null, 500);
		} catch (error) {
			return new HttpResponse(error, null, 500);
		}
	}

	async add(
		action: string,
		context: IContext = {},
		data: IParam = {}
	): Promise<IHttpResponse> {
		const {
			data: Data,
			context: Context,
		}: { data: IParam; context: IContext } = this.handleRequestData(
			context,
			data
		);
		if (Data && Data.hasOwnProperty('$rowDataState')) {
			delete Data['$rowDataState'];
		}
		let result: Promise<any> | null = null;
		try {
			await this.initEntityService();
			if (this.appEntityService) {
				result = this.appEntityService[action ? action : 'Create'](
					Context,
					Data
				);
				if (result) {
					const response = await result;
					this.handleResponse(response);
				}
			}
		} catch (error) {}
		return result;
	}

	async update(
		action: string,
		context: IContext = {},
		data: IParam = {}
	): Promise<IHttpResponse> {
		const { data: Data, context: Context } = this.handleRequestData(
			context,
			data
		);
		if (Data.hasOwnProperty('$rowDataState')) {
			delete Data['$rowDataState'];
		}
		let result: Promise<any> | null = null;
		try {
			await this.initEntityService();
			if (this.appEntityService) {
				result = this.appEntityService[action ? action : 'Update'](
					Context,
					Data
				);
				if (result) {
					const response = await result;
					this.handleResponse(response);
				}
			}
		} catch (error) {}
		return result;
	}

	async delete(
		action: string,
		context: IContext = {},
		data: IParam = {}
	): Promise<IHttpResponse> {
		const { data: Data, context: Context } = this.handleRequestData(
			context,
			data
		);
		let result: Promise<any> | null = null;
		try {
			await this.initEntityService();
			if (this.appEntityService) {
				result = this.appEntityService[action ? action : 'Remove'](
					Context,
					Data
				);
				if (result) {
					const response = await result;
					this.handleResponse(response);
				}
			}
		} catch (error) {}
		return result;
	}

	/**
	 * 设置远端数据
	 *
	 * @param result 远端请求结果
	 * @memberof GridService
	 */
	public setRemoteCopyData(result: any) {
		if (result.success) {
			this.remoteCopyData = deepCopy(result.data);
		}
	}

	/**
	 * 获取远端数据
	 *
	 * @memberof GridService
	 */
	public getRemoteCopyData() {
		return this.remoteCopyData;
	}

	/**
	 * 设置备份原生数据
	 *
	 * @param data 远端请求结果
	 * @memberof GridService
	 */
	public setCopynativeData(data: any) {
		this.copynativeData = deepCopy(data);
	}

	/**
	 * 获取备份原生数据
	 *
	 * @memberof GridService
	 */
	public getCopynativeData() {
		return this.copynativeData;
	}

	/**
	 * 获取跨实体数据集合
	 *
	 * @param {string} serviceName 服务名称
	 * @param {string} interfaceName 接口名称
	 * @param {*} data 参数
	 * @param {string} [deKeyField] 应用实体主信息属性名称
	 * @param {string} [deName] 应用实体主键属性名称
	 * @returns {*}  {Promise<any[]>}
	 * @memberof GridService
	 */
	public getItems(
		serviceName: string,
		interfaceName: string,
		context: any = {},
		data: any,
		deKeyField?: string,
		deName?: string
	): Promise<any[]> {
		data.page = data.page ? data.page : 0;
		data.size = data.size ? data.size : 1000;
		return new Promise((resolve: any, reject: any) => {
			App.getDataService(serviceName, context)
				.then(async (dataService: any) => {
					if (dataService && dataService[interfaceName] instanceof Function) {
						const response = await this.doItems(
							dataService[interfaceName](context, data),
							`${deKeyField}`,
							`${deName}`,
							dataService.appEntityTextCodeName,
							dataService.appEntityKeyCodeName
						);
						resolve(response);
					}
				})
				.catch((error: any) => {
					reject([]);
				});
		});
	}

	/**
	 * 处理数据
	 *
	 * @private
	 * @param {Promise<any>} promise
	 * @returns {Promise<any>}
	 * @memberof AppGridService
	 */
	private doItems(
		promise: Promise<any>,
		deKeyField: string,
		deName: string,
		textCodeName?: string,
		keyCodeName?: string
	): Promise<any> {
		return new Promise((resolve, reject) => {
			promise
				.then((response: any) => {
					if (response.success) {
						const data = response.data;
						data.forEach((item: any, index: number) => {
							item[deName] = item[deKeyField];
							if (textCodeName) {
								item.label = item[textCodeName];
							}
							if (keyCodeName) {
								item.value = item[keyCodeName];
							}
							data[index] = item;
						});
						resolve(data);
					} else {
						reject([]);
					}
				})
				.catch((response: any) => {
					reject([]);
				});
		});
	}

	/**
	 * 前台逻辑
	 *
	 * @param {string} action
	 * @param {IParam} [context]
	 * @param {IParam} [data]
	 * @return {*}  {Promise<IHttpResponse>}
	 * @memberof GridService
	 */
	async frontLogic(
		action: string,
		context?: IParam,
		data?: IParam
	): Promise<IHttpResponse> {
		const { data: Data, context: Context } = this.handleRequestData(
			context,
			data
		);
		try {
			await this.initEntityService();
			if (
				this.appEntityService &&
				this.appEntityService[action] &&
				this.appEntityService[action] instanceof Function
			) {
				const response: IHttpResponse = await this.appEntityService[action](
					Context,
					Data
				);
				this.handleResponse(response);
				return response;
			}
			return new HttpResponse({}, null, 500);
		} catch (error) {
			return new HttpResponse(error, null, 500);
		}
	}
}
export default GridService;
